/**
 * 
 */
package com.hexacta.hrs.repositories.impl;

import java.util.Collection;
import java.util.Date;
import java.util.List;

import org.hibernate.Criteria;
import org.hibernate.criterion.Example;
import org.hibernate.criterion.MatchMode;
import org.hibernate.criterion.Order;
import org.hibernate.criterion.Restrictions;
import org.vectrics.employee.Employee;
import org.vectrics.user.Person;

import com.hexacta.hrs.repositories.TimeOffRepository;
import com.hexacta.hrs.timeoff.Status;
import com.hexacta.hrs.timeoff.TimeOff;

/**
 * @author mfunes
 * 
 */
public class TimeOffRecordObjectRepository extends HibernateRecordObjectRepository<TimeOff> implements
        TimeOffRepository {

    /** {@inheritDoc} */
    public TimeOffRecordObjectRepository(final Class<TimeOff> entityClass) {
        super(entityClass);
    }

    /** {@inheritDoc} */
    @SuppressWarnings("unchecked")
    @Override
    public Collection<TimeOff> matching(final TimeOff criteria) {
        Criteria crit = getSession().createCriteria(TimeOff.class);

        // se crea el filtro de fecha Desde y hasta
        if (criteria.getDateFrom() != null && criteria.getDateTo() != null) {
            crit.add(

            Restrictions.or(
                    Restrictions.and(Restrictions.ge("dateFrom", criteria.getDateFrom()),
                            Restrictions.le("dateTo", criteria.getDateTo())),
                    Restrictions.or(
                            Restrictions.and(Restrictions.le("dateFrom", criteria.getDateFrom()),
                                    Restrictions.ge("dateTo", criteria.getDateFrom())),
                            Restrictions.and(Restrictions.le("dateFrom", criteria.getDateTo()),
                                    Restrictions.ge("dateTo", criteria.getDateTo())))));
            // Debo nullear la fecha para que el byExample lo ignore.
            criteria.setDateFrom(null);
            criteria.setDateTo(null);
        }

        // se crea el filtro de fecha Desde.
        if (criteria.getDateFrom() != null) {
            crit.add(Restrictions.and(Restrictions.le("dateFrom", criteria.getDateFrom()),
                    Restrictions.ge("dateTo", criteria.getDateFrom())));
            // Debo nullear la fecha para que el byExample lo ignore.
            criteria.setDateFrom(null);
        }

        // se crea el filtro de fecha Hasta.
        if (criteria.getDateTo() != null) {
            crit.add(Restrictions.and(Restrictions.le("dateFrom", criteria.getDateTo()),
                    Restrictions.ge("dateTo", criteria.getDateTo())));
            // Debo nullear la fecha para que el byExample lo ignore.
            criteria.setDateTo(null);
        }

        Example exampleTimeOff = Example.create(criteria).ignoreCase().enableLike(MatchMode.ANYWHERE);
        crit.add(exampleTimeOff);
        // Se crea el filtro de Employee.
        if (criteria.getEmployee() != null) {
            Example exampleEmployee = Example.create(criteria.getEmployee()).ignoreCase()
                    .enableLike(MatchMode.ANYWHERE);
            crit.createCriteria("employee").add(exampleEmployee);
        }
        // Se crea el filtro de Status.
        if (criteria.getCurrentStatusDetail() != null) {
            Example exampleStatus = Example.create(criteria.getCurrentStatusDetail()).ignoreCase()
                    .enableLike(MatchMode.ANYWHERE);
            crit.createCriteria("currentStatus").add(exampleStatus);
        }

        // Se lo agrega para que solo traiga una sola instacia del timeOff.
        crit.setResultTransformer(Criteria.DISTINCT_ROOT_ENTITY);

        // Ordena de la fecha mas reciente a la mas antigua
        crit.addOrder(Order.desc("dateFrom"));

        // Se devuelven los filtros.
        return crit.list();
    }

    /*
     * (non-Javadoc)
     * 
     * @see
     * com.hexacta.hrs.repositories.TimeOffRepository#findTimeOff(org.vectrics
     * .employee.Employee, java.util.Date, java.util.Date)
     */
    @Override
    public Collection<TimeOff> findTimeOff(final Employee employee, final Date from, final Date to,
            final List<Status> statusToShow) {
        Criteria crit = getSession().createCriteria(TimeOff.class);
        crit.add(Restrictions.eq("employee", employee));
        crit.add(Restrictions.le("dateFrom", to));
        crit.add(Restrictions.ge("dateTo", from));
        crit.createCriteria("currentStatus").add(Restrictions.in("status", statusToShow));
        return crit.list();
    }

    /*
     * (non-Javadoc)
     * 
     * @see
     * com.hexacta.hrs.repositories.TimeOffRepository#getPendingApprovalEmployees
     * ()
     */
    @Override
    public List<Person> getPendingApprovalEmployees() {
        String query = "SELECT distinct to.currentStatus.approvedBy.person FROM TimeOff to "
                + "WHERE to.currentStatus.status = 'REQUESTED' "
                + "AND mod(datediff(current_date(),to.currentStatus.transitionDate),2)=0 "
                + "AND datediff(current_date(),to.currentStatus.transitionDate) <> 0";

        return getSession().createQuery(query).list();
    }
}
